package stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.junit.Test;

public class StreamTest {
	// List,set,array
	List<String> list = Arrays.asList("abc","def","www","hhhh","hello","world","abc","def");
	int[] arr = {1,2,2,41,13,1};
	Set<Double> set = new HashSet<>();
	
	@Test
	public void create() {
		
		Stream.of(1,3,32,42,432,412);
		
		// 1.集合创建流  
		Stream<String> stream = list.stream();
		stream.forEach((s)->System.out.println(s));
		System.out.println("------------------------");
		
		// 并发流(多线程使用)
		Stream<String> parallelStream = list.parallelStream();
		parallelStream.forEach((s)->System.out.println(s));
		System.out.println("------------------------");
		
		// 2.通过数组创建流
		IntStream stream2 = Arrays.stream(arr);
		stream2.forEach((s)->System.out.println(s));
		System.out.println("------------------------");
		
		// 3.随机数产生一个流
		Random rand = new Random();
		IntStream ints = rand.ints(10);
		ints.forEach((s)->System.out.println(s));
		System.out.println("------------------------");
		
		Collections.addAll(set, 1.1,2.2,3.3,4.4);
		Stream<Double> stream3 = set.stream();
		stream3.forEach((s)->System.out.println(s));
	}

	@Test
	public void methods() {
		// 1.count求元素个数
		long count = list.stream().count();
		System.out.println(count);
	
		// 2.去重
		Stream<String> distinct = list.stream().distinct();
		distinct.forEach(s->System.out.println(s));
		
		// 3.判断是否是并发流
		boolean parallel = list.stream().isParallel();
		System.out.println(parallel);
		
		// 4.要前几个
		Stream<String> limit = list.stream().limit(3);
		limit.forEach(t->System.out.println(t));
		
		// 5.排序(小到大)
		Stream<String> sorted = list.stream().sorted();
		sorted.forEach(t->System.out.println(t));
		
		System.out.println("-----------------------");
		// 6.所有返回流都可以继续调用 
		// distinct: "abc","def","www","hhhh","hello","world"
		// sorted: abc def hello hhhh world www
		// skip: hello hhhh world www
		// limit: hello hhhh world
		list.stream().distinct().sorted().skip(2).limit(3).forEach(t->System.out.println(t));
		
		// 7.判断是否有任何一个满足条件       Predicate
		System.out.println(list.stream().anyMatch(t->t.equals("hello")));
		// 必须所有元素都满足才返回true   Predicate
		System.out.println(list.stream().allMatch(t-> !t.isEmpty()));
		
	}
	
	@Test
	public void filter() {
		// Predicate断言接口 -> boolean test(T ) : 条件为真留下，为假过滤掉
		/*
		list.stream().filter(new Predicate<String>() {
			@Override
			public boolean test(String t) {
				return t.length() >= 4;
			}
		}).forEach(t->System.out.println(t));
		*/
		
		list.stream().filter((t)->t.length()>=4).forEach(t->System.out.println(t));
		// 以h开头的留下
		list.stream().filter(t-> t.startsWith("h")).forEach(t->System.out.println(t));
	}
	
	@Test
	public void map() {
		// Function<T,R> 函数接口: R apply(T)
		/*
		list.stream().map(new Function<String, String>() {
			@Override   // 参数t就是遍历的对象
			public String apply(String t) {
				return t.toUpperCase();
			}
		}).forEach(t->System.out.println(t));
		*/
		
		list.stream().map(t->t.toUpperCase()).forEach(t->System.out.println(t));
		
		// 每个字符串截取前3个字符
		list.stream().map(t->t.substring(0,3)).forEach(t->System.out.println(t));
		// 每个字符串后连接一个😊
		list.stream().map(t->t.concat("😊")).forEach(t->System.out.println(t));
		
		// 处理后返回其他类型也可以
		list.stream().map(t->t.length()).forEach(t->System.out.println(t));
		list.stream().map(t->t.isEmpty()).forEach(t->System.out.println(t));
		
	}
	
	@Test
	public void reduce() {
		// reduce收汁
		IntStream stream = Arrays.stream(arr);
		
		// {1,2,2,41,13,1};
		OptionalInt reduce = stream.reduce((left,right)->  left + right);
		
		System.out.println(reduce.getAsInt());
		
		// 拼接
		Optional<String> reduce2 = list.stream().reduce((a,b)->a.concat("-").concat(b));
		System.out.println(reduce2.get());
	}
	
	@Test
	public void collect() {
		
		List<Integer> list2 = new ArrayList<>();
		Collections.addAll(list2, 100,88,120,23,5,67);
		
		// 可以处理统计   summarizing:总结,概括,概述
		IntSummaryStatistics collect = list2.stream().collect(Collectors.summarizingInt(t->t));
		System.out.println(collect.getMax());      // 最大值
		System.out.println(collect.getMin());      // 最小值
		System.out.println(collect.getAverage());  // 平均数
		System.out.println(collect.getSum());      // 求和
		System.out.println(collect.getCount());    // 个数
		
		// join拼接, arg0:使用什么拼接
		String collect2 = list.stream().collect(Collectors.joining(","));
		// join拼接, arg0:使用什么拼接   arg1:拼接前缀，  arg2:拼接后缀
		String collect3 = list.stream().collect(Collectors.joining(",","[","]"));
		System.out.println(collect3);
		
		List<Student> students = new ArrayList<>();
		students.add(new Student(1,"a","1班",90));
		students.add(new Student(2,"b","2班",80));
		students.add(new Student(3,"c","1班",70));
		students.add(new Student(4,"d","2班",88));
		students.add(new Student(5,"e","1班",92));
		students.add(new Student(6,"f","2班",75));
		
		// 根据班级分组， 1
		Map<String, List<Student>> map = students.stream().   // groupingBy 依据分组的属性，值相同分为一组
				                         collect(Collectors.groupingBy(s -> ((Student)s).getClassName()));
		map.forEach((k,v)-> System.out.println(k +"\n\t" + v));
		
		// 练习，90分一组，80分一组，70分一组
		Map<Integer, List<Student>> map2 = students.
				// Collectors.groupingBy(Function<R,T>)
				stream().collect(Collectors.groupingBy(s -> ((Student)s).getScore()/10));
		map2.forEach((k,v)-> System.out.println(k +"\n\t" + v));
		
		// Collectors.groupingBy(Function<R,T>, Collector);
		// 根据班级分组后统计每个班级人数
		Map<String, Long> map3 = students.stream()
		        .collect(
		        		Collectors.groupingBy(s -> ((Student)s).getClassName(),
		        				              Collectors.counting()));
		map3.forEach((k,v)-> System.out.println(k +"\n\t" + v));
		
		// 根据班级分组后统计每个班级成绩和
		Map<String, Integer> map4 = students.stream()
		        .collect(
		        		Collectors.groupingBy(s -> ((Student)s).getClassName(),
		        				              // 分组后的集合遍历给s赋值
		        				              Collectors.summingInt(s->((Student)s).getScore()))
		        		);
		map4.forEach((k,v)-> System.out.println(k +"\n\t" + v));
	
		
		long count = students.stream().filter(s->s.getClassName().equals("1班"))
		                 .filter(s -> s.getScore()>=90).count();
		System.out.println(count);
	}
}















